HEX
Server: LiteSpeed
System: Linux eticaretsrv4.isimtescil.net 3.10.0-962.3.2.lve1.5.26.7.el7.x86_64 #1 SMP Wed Oct 2 07:53:12 EDT 2019 x86_64
User: sioberen (1086)
PHP: 7.3.33
Disabled: NONE
Upload Files
File: //proc/self/root/opt/alt/python37/lib/python3.7/site-packages/clpackages/clquota_packages_lib.py
# -*- coding: utf-8 -*-

# clquota_packages_lib.py - module for interfacing with lvectl utility for get/set package inodes limits
#
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT

from __future__ import absolute_import
import csv
from cllimits.lib import exec_utility
from cllimits import ClQuotaException
from cllimits.lib.utils import is_quota_supported, is_quota_active


class ClQuotaPackage(object):

    def __init__(self):
        self._CL_QUOTA_PATH = '/usr/bin/cl-quota'
        self._REPQUOTA_PATH = '/usr/sbin/repquota'
        # Error flag
        self._is_clquota_error = False
        # Check if quota is supported
        self._is_clquota_present = is_quota_supported(self._CL_QUOTA_PATH, self._REPQUOTA_PATH)
        # Check if quota is activated
        self._is_clquota_activated = is_quota_active(self._CL_QUOTA_PATH, self._REPQUOTA_PATH)
        # indodes packages limits dictionary: {package_name: { "soft": 100000, "hard": 200000 } }
        self._inode_package_dict = None

    def is_clquota_present(self):
        """
        Get cl-quota presence flag
        :return: Quota utilities presence flag
        """
        return self._is_clquota_present

    def is_clquota_activated(self):
        """
        Get quota activated flag
        :return: True/False - quotas present/not present
        """
        return self._is_clquota_activated

    def _load_info(self):
        """
        Loads packages info from cl-quota
        :return: None
        """
        # Exit if cl-quota data already loaded
        if self._inode_package_dict is not None:
            return
        disabled_exc_message = {'message': "%(util)s is disabled",
                                'context': {'util': 'Quota'}}
        # Exit if cl-quota not present or cl-quota error
        if not self._is_clquota_present or not self._is_clquota_activated or self._is_clquota_error:
            raise ClQuotaException(disabled_exc_message)
        # Get all cl-quota limits and parse them to self._inodes_limits
        # /usr/bin/cl-quota --all-package-limits --csv
        ret_code, s_quota_limits = exec_utility(self._CL_QUOTA_PATH, ['--csv', '--all-package-limits'])
        if ret_code != 0:
            # Error
            self._is_clquota_error = True
            raise ClQuotaException(disabled_exc_message)
        reader = csv.reader(s_quota_limits.split('\n'), delimiter=',')
        self._inode_package_dict = dict()
        header_found = False
        for row in reader:
            if 'ERROR' in row:
                # Error
                self._is_clquota_error = True
                # Remove data dictionary
                self._inode_package_dict = None
                raise ClQuotaException(disabled_exc_message)
            # Pass 1st line - header
            if not header_found:
                header_found = True
                continue
            # Put data to result dictionary
            if row[2] == '-':
                soft_limit = 0
            else:
                soft_limit = int(row[2])
            if row[3] == '-':
                hard_limit = 0
            else:
                hard_limit = int(row[3])
            self._inode_package_dict[row[0]] = {'soft': soft_limit, 'hard': hard_limit}

    def get_reseller_package_limits(self, package_name_arg):
        """
        Get inodes limits for supplied reseller and package
        :param package_name_arg: Package name. Only if reseller name is provided. If None - all packages
        :return: Packages limits dictionary: {package_name: { "soft": 100000, "hard": 200000 } }
        If package with supplied name not found, dictionary will be empty
        """
        self._load_info()
        if not package_name_arg:
            # if package name not provided - return all packages
            return self._inode_package_dict
        # Package name provided
        if package_name_arg in self._inode_package_dict:
            return {package_name_arg: self._inode_package_dict[package_name_arg]}
        return {}

    def __set_error(self, param, package_name, err):
        return {'message': "%(what)s set error for package=%(package)s%(error)s",
                'context': {'what': param, 'package': package_name,
                            'error': " [%s]" % err if err else ""}}

    def set_reseller_package_limits(self, package_name, limits_to_set):
        """
        Set inodes limits for package
        :param package_name: Package name
        :param limits_to_set: Limits to set: soft_limit,hard_limit
        :return: None
        """
        disabled_exc_message = {'message': "%(util)s is disabled",
                                'context': {'util': 'Quota'}}
        # Exit if cl-quota not present or cl-quota error
        if not self._is_clquota_present or not self._is_clquota_activated:
            raise ClQuotaException(disabled_exc_message)
        limits = limits_to_set.split(',')
        if len(limits) != 2:
            # Argument error
            raise ClQuotaException({'message': "%(util)s argument error",
                                    'context': {'util': 'cl-quota'}})
        # set quotas limits
        cl_quota_cmd = ['--package=%s' % package_name,
                        '--soft=%s' % limits[0], '--hard=%s' % limits[1]]
        ret_code, stdout = exec_utility(self._CL_QUOTA_PATH, cl_quota_cmd)
        if ret_code != 0 or stdout:
            # Set limits error
            raise ClQuotaException(self.__set_error('Inodes limits', package_name, stdout))